/**
 * Automatic Subtitle Downloader
 * http://code.google.com/p/autosubdown/
 * 
 * Copyright 2010-2011 Raphael Medeiros.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 */
package com.byraphaelmedeiros.autosubdown.domain;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.thoughtworks.xstream.annotations.XStreamOmitField;

/**
 * @author Raphael Medeiros
 *
 */
public class Rule {

	private long id;
	
	private String name;
	
	private String searchFor;
	
	private String notInclude;
	
	private String episode; // 1-2,1-25 (S,E)
	
	private List<String> episodesDownloaded = new ArrayList<String>();
	
	private String downloadTo;
	
	@XStreamOmitField
	private String contentUsed;

	
	public Rule() {
	}
	
	public Rule(long id) {
		this.id = id;
	}
	
	public Rule(long id, String name, String searchFor, String notInclude, String episode, String downloadTo) {
		this.id = id;
		this.name = name;
		this.searchFor = searchFor;
		this.notInclude = notInclude;
		this.episode = episode;
		this.downloadTo = downloadTo;
	}

	/**
	 * @return the id
	 */
	public long getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the searchFor
	 */
	public String getSearchFor() {
		return searchFor;
	}

	/**
	 * @param searchFor the rule to set
	 */
	public void setSearchFor(String searchFor) {
		this.searchFor = searchFor;
	}

	/**
	 * @return the notInclude
	 */
	public String getNotInclude() {
		return notInclude;
	}

	/**
	 * @param notInclude the not to set
	 */
	public void setNotInclude(String notInclude) {
		this.notInclude = notInclude;
	}

	/**
	 * @return the episode
	 */
	public String getEpisode() {
		return episode;
	}

	/**
	 * @param episode the episode to set
	 */
	public void setEpisode(String episode) {
		this.episode = episode;
	}

	/**
	 * @return the episodesDownloaded
	 */
	public List<String> getEpisodesDownloaded() {
		return episodesDownloaded;
	}

	/**
	 * @param episodesDownloaded the episodesDownloaded to set
	 */
	public void setEpisodesDownloaded(List<String> episodesDownloaded) {
		this.episodesDownloaded = episodesDownloaded;
	}

	/**
	 * @return the downloadTo
	 */
	public String getDownloadTo() {
		return downloadTo;
	}

	/**
	 * @param downloadTo the downloadTo to set
	 */
	public void setDownloadTo(String downloadTo) {
		this.downloadTo = downloadTo;
	}

	/**
	 * @return the contentUsed
	 */
	public String getContentUsed() {
		return contentUsed;
	}

	/**
	 * @param contentUsed the contentUsed to set
	 */
	public void setContentUsed(String contentUsed) {
		this.contentUsed = contentUsed;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (id ^ (id >>> 32));
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Rule other = (Rule) obj;
		if (id != other.id)
			return false;
		return true;
	}
	
	public boolean inRule(String content) {
		setContentUsed(content);
		
		if (StringUtils.containsIgnoreCase(content, notInclude))
			return false;
		
		if (!StringUtils.containsIgnoreCase(content, searchFor))
			return false;
		
		
		if (isTVShow()) {
			String[] search = episode.split(",");
			
			if (search.length == 2) {
				String seasonSearch = search[0];
				String episodeSearch = search[1];
				
				int seasonStart = 0;
				int seasonEnd = 0;
				int episodeStart = 0;
				int episodeEnd = 0;
				
				boolean isSeasonRange = false;
				boolean isEpisodeRange = false;
				
				// verifica se a temporada esta em intervalo
				if (seasonSearch.contains("-")) {
					String[] seasonRange = seasonSearch.split("-");
					
					if (seasonRange.length == 2) {
						seasonStart = Integer.parseInt(seasonRange[0]);
						seasonEnd = Integer.parseInt(seasonRange[1]);
						
						isSeasonRange = true;
					}
				}
				
				// verifica se o episodio esta em intervalo
				if (episodeSearch.contains("-")) {
					String[] episodeRange = episodeSearch.split("-");
					
					if (episodeRange.length == 2) {
						episodeStart = Integer.parseInt(episodeRange[0]);
						episodeEnd = Integer.parseInt(episodeRange[1]);
						
						isEpisodeRange = true;
					}
				}
				
				String rangeSearch = "";
				
				if (isSeasonRange && isEpisodeRange) {
					for (int s = seasonStart; s <= seasonEnd; s++) {
						for (int e = episodeStart; e <= episodeEnd; e++) {
							rangeSearch = "S" + String.format("%02d", s) + "E" + String.format("%02d", e);
							
							if (StringUtils.containsIgnoreCase(content, rangeSearch) && !isEpisodeDownloaded(rangeSearch))
								return true;
						}
					}
					
					return false;
				} else if (!isSeasonRange && isEpisodeRange) {
					for (int e = episodeStart; e <= episodeEnd; e++) {
						rangeSearch = "S" + String.format("%02d", Integer.parseInt(seasonSearch)) + "E" + String.format("%02d", e);
						
						if (StringUtils.containsIgnoreCase(content, rangeSearch) && !isEpisodeDownloaded(rangeSearch))
							return true;
					}
					
					return false;
				} else if (isSeasonRange && !isEpisodeRange) {
					for (int s = seasonStart; s <= seasonEnd; s++) {
						rangeSearch = "S" + String.format("%02d", s) + "E" + String.format("%02d", episodeSearch);
						
						if (StringUtils.containsIgnoreCase(content, rangeSearch) && !isEpisodeDownloaded(rangeSearch))
							return true;
					}
					
					return false;
				}
			}
		}
		
		return true;
	}
	
	/**
	 * @param rangeSearch
	 * @return
	 */
	private boolean isEpisodeDownloaded(String rangeSearch) {
		return (episodesDownloaded.contains(rangeSearch));
	}

	public String getFileName() {
		String suffix = "";
		
		if (isTVShow())
			suffix = "-" + getEpisode(contentUsed);
		
		return name.toLowerCase().replaceAll(" ", "_") + suffix;
	}
	
	public boolean isTVShow() {
		return (episode != null && !"".equals(episode.trim()));
	}
	
	public void addEpisodeDownloaded(String episode) {
		episodesDownloaded.add(episode);
	}
	
	public String getEpisode(String content) {
		if (isTVShow()) {
			String[] search = episode.split(",");
			
			if (search.length == 2) {
				String seasonSearch = search[0];
				String episodeSearch = search[1];
				
				int seasonStart = 0;
				int seasonEnd = 0;
				int episodeStart = 0;
				int episodeEnd = 0;
				
				boolean isSeasonRange = false;
				boolean isEpisodeRange = false;
				
				// verifica se a temporada esta em intervalo
				if (seasonSearch.contains("-")) {
					String[] seasonRange = seasonSearch.split("-");
					
					if (seasonRange.length == 2) {
						seasonStart = Integer.parseInt(seasonRange[0]);
						seasonEnd = Integer.parseInt(seasonRange[1]);
						
						isSeasonRange = true;
					}
				}
				
				// verifica se o episodio esta em intervalo
				if (episodeSearch.contains("-")) {
					String[] episodeRange = episodeSearch.split("-");
					
					if (episodeRange.length == 2) {
						episodeStart = Integer.parseInt(episodeRange[0]);
						episodeEnd = Integer.parseInt(episodeRange[1]);
						
						isEpisodeRange = true;
					}
				}
				
				String rangeSearch = "";
				
				if (isSeasonRange && isEpisodeRange) {
					for (int s = seasonStart; s <= seasonEnd; s++) {
						for (int e = episodeStart; e <= episodeEnd; e++) {
							rangeSearch = "S" + String.format("%02d", s) + "E" + String.format("%02d", e);
							
							if (StringUtils.containsIgnoreCase(content, rangeSearch) && !isEpisodeDownloaded(rangeSearch))
								return rangeSearch;
						}
					}
				} else if (!isSeasonRange && isEpisodeRange) {
					for (int e = episodeStart; e <= episodeEnd; e++) {
						rangeSearch = "S" + String.format("%02d", Integer.parseInt(seasonSearch)) + "E" + String.format("%02d", e);
						
						if (StringUtils.containsIgnoreCase(content, rangeSearch) && !isEpisodeDownloaded(rangeSearch))
							return rangeSearch;
					}
				} else if (isSeasonRange && !isEpisodeRange) {
					for (int s = seasonStart; s <= seasonEnd; s++) {
						rangeSearch = "S" + String.format("%02d", s) + "E" + String.format("%02d", Integer.parseInt(episodeSearch));
						
						if (StringUtils.containsIgnoreCase(content, rangeSearch) && !isEpisodeDownloaded(rangeSearch))
							return rangeSearch;
					}
				}
			}
		}
		
		return null;
	}
}